<script setup lang="ts">
import type { Ref } from 'vue'
import type { componentType } from '../componentPanel/index'
import type { FormBasicConfig } from '../type'
import { ElButton, ElForm, ElFormItem, ElIcon } from 'element-plus'
import { computed, inject, ref, watch } from 'vue'
import draggable from 'vuedraggable'
import { getComponent } from '../componentPanel/index'
import { parseAttrs } from '../utils'
import HeaderBar from './headerBar.vue'

const emit = defineEmits(['selectComponent', 'dragAdd'])
const componentsPanel = inject('componentsPanel') as Ref<componentType[]>
const formModel = ref<Record<string, any>>({})
const formRules = ref<Record<string, any>>({})
const formRef = ref<InstanceType<typeof ElForm>>()
const selectRowIndex = ref(-1)

const formBasicConfig = inject('formBasicConfig') as Ref<FormBasicConfig>

// 计算网格容器样式
const gridContainerStyle = computed(() => ({
  display: 'grid',
  gridTemplateColumns: `repeat(${formBasicConfig.value.totalColumns}, 1fr)`,
  gap: `${formBasicConfig.value.gridGap}px`,
}))

// 选中组件并传递事件
function handleSelect(index: number) {
  selectRowIndex.value = index
  emit('selectComponent', componentsPanel.value[index])
}

// 初始化表单数据
function initFormData() {
  componentsPanel.value.forEach((item) => {
    const field = item.options.field
    if (field) {
      formModel.value[field] = item.options.defaultValue ?? ''
      if (item.options.rules) {
        formRules.value[field] = item.options.rules
      }
      if (item.options.span === undefined) {
        item.options.span = 3
      }
      // 限制colSpan最大值不超过总列数
      if (item.options.span > formBasicConfig.value.totalColumns) {
        item.options.span = formBasicConfig.value.totalColumns
      }
    }
  })
}

function handleDelete(index: number) {
  componentsPanel.value.splice(index, 1)
}

// 拖拽交互
const isDragover = ref(false)

function handleAdd(e: any) {
  isDragover.value = false
  emit('dragAdd', e.newDraggableIndex)
}
function handleCancelSelect() {
  selectRowIndex.value = -1
}

watch(componentsPanel, initFormData, { immediate: true })
</script>

<template>
  <HeaderBar @cancel-select="handleCancelSelect" />
  <ElForm ref="formRef" :model="formModel" :rules="formRules" label-width="100px" class="dynamic-form">
    <draggable
      v-model="componentsPanel" group="form-components" class="grid-container" :style="gridContainerStyle"
      :animation="150" ghost-class="grid-ghost" chosen-class="grid-chosen" drag-class="grid-dragging" @add="handleAdd"
    >
      <template #item="{ element, index }">
        <div
          class="grid-item" :style="{
            gridColumn: `span ${element.options.span}`,
          }"
        >
          <ElFormItem
            :label="element.options.label" :label-width="element.options.labelWidth"
            :prop="element.options.field" class="form-item "
            :class="{ 'form-item-active': selectRowIndex === index }" @click.stop="handleSelect(index)"
          >
            <component
              :is="getComponent(element.options.component)" v-model="formModel[element.options.field]"
              v-bind="parseAttrs(element.options.attrs)" :validate-event="false" :disabled="true" class=" flex-1 non-interactive"
            >
              <template v-if="element.options.component === 'radioGroup'">
                <ElRadio
                  v-for="item in element.options.selectOptions" :key="item.value" :label="item.value"
                  :disabled="parseAttrs(element.options.attrs).disabled"
                >
                  {{ item.label }}
                </ElRadio>
              </template>
              <template v-if="element.options.component === 'checkboxGroup'">
                <ElCheckbox
                  v-for="item in element.options.selectOptions" :key="item.value" :label="item.value"
                  :disabled="parseAttrs(element.options.attrs).disabled"
                >
                  {{ item.label }}
                </ElCheckbox>
              </template>
            </component>
            <ElButton v-if="selectRowIndex === index" class="delete-btn" title="删除组件" @click.stop="handleDelete(index)">
              <ElIcon>
                <Delete />
              </ElIcon>
            </ElButton>
          </ElFormItem>
        </div>
      </template>
      <template v-if="componentsPanel.length === 0" #footer>
        <div class="empty-state">
          <el-empty :image-size="200" description="从左侧拖拽组件到此处" />
        </div>
      </template>
    </draggable>
  </ElForm>
</template>

<style scoped>
.dynamic-form {
  background: #fff;
  padding-top: 50px;
  /* border-radius: 6px; */
  /* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); */
}

/* 网格容器样式 */
.grid-container {
  width: 100%;
  box-sizing: border-box;
  transition: all 0.3s ease;
}

/* 网格项样式 */
.grid-item {
  box-sizing: border-box;
}

/* 表单项样式 */
.form-item {
  width: 100%;
  background: #fff;
  border-radius: 4px;
  transition: all 0.3s ease;
}

.non-interactive {
  pointer-events: none;
}

.form-item-active {
  border-color: var(--el-color-primary-light-9);
  background-color: var(--el-color-primary-light-9);
  padding: 10px;
}

.form-item:hover {
  border-color: var(--el-color-primary-light-9);
  background-color: var(--el-color-primary-light-9);
  padding: 10px;
}

/* 拖拽手柄样式 */
.drag-handle {
  color: #c0c4cc;
  margin-right: 15px;
  cursor: move;
  padding: 4px;
  transition: color 0.2s;
}

.drag-handle:hover {
  color: var(--el-color-primary);
}

/* 删除按钮样式 */
.delete-btn {
  color: var(--el-color-danger);
  background: transparent;
  border: none;
  padding: 4px;
  margin-left: 15px;
  cursor: pointer;
  transition:
    color 0.2s,
    transform 0.2s;
}

.delete-btn:hover {
  color: var(--el-color-danger);
  transform: scale(1.1);
}

.delete-btn:focus {
  outline: none;
}

/* 拖拽状态样式 */
:deep(.grid-ghost) {
  background: rgba(64, 158, 255, 0.1);
  border: 2px dashed var(--el-color-primary);
  border-radius: 4px;
  min-height: 30px;
  grid-column: span 8;
}

:deep(.grid-chosen) {
  border-color: var(--el-color-primary) !important;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

:deep(.grid-dragging) {
  opacity: 0.8;
  transform: scale(1.02);
}

/* 空状态样式 */
.empty-state {
  position: absolute;
  width: 100%;
  text-align: center;
  color: #909399;
  border-radius: 4px;
  grid-column: span 24;
}

.empty-state i {
  font-size: 48px;
  margin-bottom: 16px;
  color: #c0c4cc;
}

/* 按钮区域样式 */
.form-actions {
  width: 100%;
  padding-top: 15px;
  display: flex;
  justify-content: flex-end;
}
</style>
